#include "test.h"
#if 0
namespace wanghao
{
    void swap(int& left,int& right)
    {
        int tmp = left;
        left = right;
        right = tmp;
    }
    void swap(double& left,double& right)
    {
        double tmp = left;
        left = right;
        right = tmp;
    }
    void swap(char& left,char& right)
    {
        char tmp = left;
        left = right;
        right = tmp;
    }
    //函数模板
    //泛型编程 - 广泛的类型来编程 - T是Type的缩写
    template<typename T>
    void swap(T& left,T& right)
    {
        T tmp = left;
        left = right;
        right = tmp;
    }
}
void swap_test()
{
    int x = 12;
    int y = 21;
    cout << "交换前:x->" << x << ":" << "y->" << y << endl;
    wanghao::swap(x,y);
    cout << "交换后:x->" << x << ":" << "y->" << y << endl;
}
namespace wanghao
{
    //函数模板
    template<class T>
    T Add(const T& x,const T& y)
    {
        return x + y;
    }
}
void add_test()
{
    int a1 = 10,a2 = 20;
    double d1 = 10.1, d2 = 20.2;
    //自动推导类型 - 隐式实例化
    cout << wanghao::Add(a1,a2) << endl;
    cout << wanghao::Add(d1,d2) << endl;
    cout << wanghao::Add((double)a1,d2) << endl;
    cout << wanghao::Add(a2,(int)d1) << endl;
    //不用推导 - 显示实例化

    cout << wanghao::Add<int>(a1,a2) << endl;
    cout << wanghao::Add<double>(d1,d2) << endl;
    cout << wanghao::Add<double>(a1,d2) << endl;
    cout << wanghao::Add<int>(a2,d1) << endl;

    //严格来说还是写两个模板参数比较好一些
}
namespace wanghao
{
    template<typename T>
    T* Func(size_t n)
    {
        return new T[n];
    }
}
void func_test()
{
    //必须显示实例化支持,没办法推导T的类型
    int* arr = wanghao::Func<int>(10);
}

int Add(int left,int right)
{
    return left + right;
}
template<typename T>
T Add(T left,T right)
{
    return (left + right) * 5;
}
template<typename T1,class T2>
T1 Add(T1 left,T2 right)
{
    return (left + right) * 10;
}
void AddTest()
{
    //有现成的就吃现成的,除非显示实例化
    cout << Add(1,2) << endl;
    cout << Add<int>(1,2) << endl;
    //不匹配的话肯定也是调模板，同一个类型的话会优先调同一个类型的
    cout << Add(1.1,2.2) << endl;
    //调不同类型的
    cout << Add(1,2.2) << endl;

    //编译器通过函数模板生成的函数和我们自己写的函数不会冲突,因为编译器
    //生成的函数会在函数名上做区分,比如Add<int>
}
//类模板
template<class T>
class Stack
{
public:
    Stack(size_t capacity = 4)
    {
        _arr = new T[capacity];
        _capacity = capacity;
        _size = 0;
    }
    void push(const T& val);
private:
    T* _arr;
    size_t _size;
    size_t _capacity;
};
//类里面声明,类外面定义,这里不能用类名代表类型,要加模板参数
template<class T>
void Stack<T>::push(const T& val)
{
    //扩容等逻辑
}
void class_test()
{
    //实例化生成对应的类,这里是两个不同的类型
    Stack<int> s1;
    Stack<double> s2;
}

//非类型模板参数,而且非类型模板参数智能适用于整型
template<class T,size_t N = 10>
class Stack
{
public:

private:
    T* _arr[N];
    size_t top;
};

//C++20才支持
template<class T,double n = 10.1>
class Array
{
public:

private:
};

//模板的特化 - 特殊化处理
//函数模板的特化
template<class T>
bool Less(T left,T right)
{
    return left < right;
}
void tempTest()
{
    cout << Less(1,2) << endl;
    Date d1(2022,7,7);
    Date d2(2022,7,8);
    cout << Less(d1,d2) << endl;
}
//特化部分:博客:模板进阶
#endif
int main()
{
    cout << Add(10,20) << endl;
    cout << Add(1.2,3.4) << endl;
    cout << Add('0','1') << endl;
    Func(1);
    return 0;
}